package com.thysdy.flowable.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.thysdy.flowable.entity.*;
import com.thysdy.flowable.enums.CodeEnum;
import com.thysdy.flowable.exception.MyException;
import com.thysdy.flowable.flowable.BaseProcessService;
import com.thysdy.flowable.mapper.ShortmessageConfigMapper;
import com.thysdy.flowable.mapper.UserMapper;
import com.thysdy.flowable.vo.ReturnVo;
import com.thysdy.flowable.vo.SendShortMessageVo;
import lombok.extern.slf4j.Slf4j;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.task.api.Task;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class CommonService extends BaseProcessService {
    @Resource
    UserMapper userMapper;
    @Resource
    MessageCenter messageCenter;
    @Resource
    RestTemplate restTemplate;
    @Resource
    ShortmessageConfigMapper shortmessageConfigMapper;

    /**
     * 给用户发送消息
     *
     * @param userIds
     */
    public void sendMessageToUsers(List<String> userIds, String message, Boolean isSendTextMessage) throws MyException {
        try {
            if (null != userIds && !userIds.isEmpty() && StringUtils.isNotBlank(message)) {
                SendMessage sendMessage = new SendMessage();
                sendMessage.setSendUser("flowableAdmin");
                sendMessage.setMessageBody(message);
                sendMessage.setMessageTitle("审批提示消息");
                sendMessage.setMessageTypeId("5");
                sendMessage.setMsgLevel("2");
                List<SendPoint> sendPoints = new ArrayList<>();
                userIds.forEach(x -> sendPoints.add(new SendPoint("/flowable", x)));
                sendMessage.setSendPointList(sendPoints);
                messageCenter.sendMessage(sendMessage);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("===>sendMessageToUsers error!", e);
            throw new MyException(CodeEnum.commonException);
        }

    }

    /**
     * 给角色下所有用户发送消息
     *
     * @param roles
     */
    public void sendMessageToGroups(List<String> roles, String message, Boolean isSendTextMessage) throws MyException {
        try {
            if (null != roles && !roles.isEmpty() && StringUtils.isNotBlank(message)) {
                SendMessage sendMessage = new SendMessage();
                sendMessage.setSendUser("flowableAdmin");
                sendMessage.setMessageBody(message);
                sendMessage.setMessageTitle("审批提示消息");
                sendMessage.setMessageTypeId("5");
                sendMessage.setMsgLevel("2");
                //查询角色下所有用户
                List<ActIdUser> users = userMapper.getUsersByRoles(roles);
                List<SendPoint> sendPoints = new ArrayList<>();
                users.forEach(x -> sendPoints.add(new SendPoint("/flowable", x.getId())));
                sendMessage.setSendPointList(sendPoints);
                messageCenter.sendMessage(sendMessage);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("===>sendMessageToUsers error!", e);
            throw new MyException(CodeEnum.commonException);
        }

    }

    /**
     * 发送消息
     *
     * @param candidates
     * @param variables
     * @param message
     */
    public void sendMessage(String assign, Set<IdentityLink> candidates, String taskKey, Map<String, Object> variables, String message, Long smsTemplateId) throws MyException {
        try {
            log.info("===>start sendMessage");
            SendMessage sendMessage = new SendMessage();
            sendMessage.setSendUser("flowableAdmin");
            sendMessage.setMessageBody(message);
            sendMessage.setMessageTitle("审批提示消息");
            sendMessage.setMessageTypeId("5");
            sendMessage.setMsgLevel("2");
            List<String> idsFirst = new ArrayList<>();
            List<String> roleIds = new ArrayList<>();
            List<String> idsSecond = new ArrayList<>();
            List<SendPoint> sendPoints = new ArrayList<>();
            if ((RequestVo.checkString(assign) || (null != candidates && !candidates.isEmpty()))) {
                if (RequestVo.checkString(assign)) {
                    idsFirst.add(assign);
                }
                if (null != candidates && !candidates.isEmpty()) {
                    candidates.parallelStream().forEach(x -> {
                        if (RequestVo.checkString(x.getUserId())) {
                            idsFirst.add(x.getUserId());
                        } else if (RequestVo.checkString(x.getGroupId())) {
                            roleIds.add(x.getGroupId());
                        }
                    });
                }
            } else {
                List<String> assignUsers = null;
                List<String> assignGroups = null;
                Map<String, Map<String, List<String>>> globalAssignSettings = null;
                //下一任务候选人
                assignUsers = (List<String>) variables.get("assignUsers");
                //下一任务候选组
                assignGroups = (List<String>) variables.get("assignGroups");
                //全局任务候选配置
                globalAssignSettings = (Map<String, Map<String, List<String>>>) variables.get("globalAssignSettings");

                if ((null == assignUsers || assignUsers.isEmpty()) && (null == assignGroups || assignGroups.isEmpty())) {
                    if (null != globalAssignSettings) {
                        if (null != taskKey) {
                            Map<String, List<String>> taskAssignSetting = globalAssignSettings.get(taskKey);
                            if (null != taskAssignSetting) {
                                List<String> users = taskAssignSetting.get("assignUsers");
                                List<String> groups = taskAssignSetting.get("assignGroups");
                                if (null != users && !users.isEmpty()) {
                                    assignUsers = users;
                                }
                                if (null != groups && !groups.isEmpty()) {
                                    assignGroups = groups;
                                }
                            }
                        }
                    }
                }
                if (null != assignUsers && !assignUsers.isEmpty()) {
                    idsFirst.addAll(assignUsers);
                }
                if (null != assignGroups && !assignGroups.isEmpty()) {
                    roleIds.addAll(assignGroups);
                }

            }
            if (!roleIds.isEmpty()) {
                //根据角色查询用户
                idsSecond = userMapper.getUserIdByRoles(roleIds);
            }
            if (!idsFirst.isEmpty()) {
                for (String id : idsFirst) {
                    if (!idsSecond.contains(id)) {
                        idsSecond.add(id);
                    }
                }
            }
            if (null != idsSecond && !idsSecond.isEmpty()) {
                idsSecond.forEach(x -> sendPoints.add(new SendPoint("/flowable", x)));
                sendMessage.setSendPointList(sendPoints);
                if (null != smsTemplateId) {
                    ShortmessageConfig config = shortmessageConfigMapper.selectById(smsTemplateId);
                    if (null != config) {
                        SendShortMessageVo shortMessageVo = new SendShortMessageVo();
                        shortMessageVo.setSignId(config.getSignId());
                        shortMessageVo.setTemplateId(config.getTemplateId());
//                        shortMessageVo.setContent("");
                        sendMessage.setSendShortMessage(shortMessageVo);
                        log.info("<======>sendMessageVo:" + sendMessage);
                    }
                }
                messageCenter.sendMessage(sendMessage);
                log.info("===>MessageBody:" + sendMessage);
            }
        } catch (Exception e) {
            log.error("===>flowable send message error!", e);
            throw new MyException(101, "flowable发送消息错误！");
        }

    }

    /**
     * 调用服务接口
     *
     * @param url
     * @param param
     * @param params
     */
    public void callInterface(String url, String param, Map<String, Object> params) throws MyException {
        log.info("===>Ready to call interface!   url:" + url + "   param:" + param);
        try {
            Map<String, Object> myParam = null;
            String userName = null;
            String dealUserName = null;
            try {
                if (StringUtils.isNotBlank(param)) {
                    myParam = (Map<String, Object>) JSONObject.parse(param);
                }
            } catch (Exception e) {
            }
            Map<String, Object> variables = (Map<String, Object>) params.get("variables");
            String initiator = (String) variables.get("initiator");
            String processInstanceId = (String) params.get("processInstanceId");
            String processDefinitionKey = (String) params.get("processDefinitionKey");
            String businessKey = (String) params.get("businessKey");
            String dealUserId = (String) params.get("dealUserId");
            if (null != initiator && "" != initiator) {
                User user = userMapper.findUserById(initiator);
                if (null != user) {
                    userName = user.getFirstName();
                }
            }
            if (null != dealUserId && "" != dealUserId) {
                User user = userMapper.findUserById(dealUserId);
                if (null != user) {
                    dealUserName = user.getFirstName();
                }
            }
            ServiceRequestVo serviceRequestVo = new ServiceRequestVo(initiator, userName, dealUserId, dealUserName, processInstanceId,processDefinitionKey, businessKey, myParam, variables);
            //headers
            HttpHeaders requestHeaders = new HttpHeaders();
            requestHeaders.add("Content-Type", "application/json");
            HttpEntity<ServiceRequestVo> requestEntity = new HttpEntity<ServiceRequestVo>(serviceRequestVo, requestHeaders);
            log.info("===>call interface start!," + serviceRequestVo);
            ResponseEntity<ReturnVo> returnEntity = restTemplate.postForEntity(url, requestEntity, ReturnVo.class);
            log.info("===>call interface result:" + returnEntity);
            if (null != returnEntity.getBody() && returnEntity.getBody().getCode() != 200) {
                throw new MyException(returnEntity.getBody().getCode(), returnEntity.getBody().getMessage());
            }
        } catch (RestClientException e) {
            log.error("===>RestClientException!", e);
            throw new MyException(102, "RestClientException！");
        } catch (MyException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("===>flowable call interface service error!", e);
            throw new MyException(103, "flowable调用接口服务异常！");
        }

    }

    /**
     * 分配审核人，审核组
     *
     * @param assignUsers
     * @param assignGroups
     * @param instanceId
     */
    public void addAssignUserOrGroup(List<String> assignUsers, List<String> assignGroups, Map<String, Map<String, List<String>>> globalAssignSettings, String instanceId, Task nextTask) throws MyException {

        try {
            if (((null != assignUsers && !assignUsers.isEmpty()) || (null != assignGroups && !assignGroups.isEmpty()) || (null != globalAssignSettings && !globalAssignSettings.isEmpty())) && null != instanceId) {
                //查询下一用户任务
                if (null == nextTask) {
                    nextTask = taskService.createTaskQuery().processInstanceId(instanceId).singleResult();
                }
                if (null != nextTask) {
                    String key = nextTask.getTaskDefinitionKey();
                    String nextTaskId = nextTask.getId();
                    if ((null == assignUsers || assignUsers.isEmpty()) && (null == assignGroups || assignGroups.isEmpty())) {
                        if (null != globalAssignSettings && !globalAssignSettings.isEmpty()) {
                            if (null == assignUsers) {
                                assignUsers = new ArrayList<>();
                            }
                            if (null == assignGroups) {
                                assignGroups = new ArrayList<>();
                            }
                            try {
                                Map<String, List<String>> stringListMap = globalAssignSettings.get(key);
                                try {
                                    List<String> users = stringListMap.get("assignUsers");
                                    if (null != users && !users.isEmpty()) {
                                        assignUsers.addAll(users);
                                    }
                                } catch (Exception e) {
                                }
                                try {
                                    List<String> groups = stringListMap.get("assignGroups");
                                    if (null != groups && !groups.isEmpty()) {
                                        assignGroups.addAll(groups);
                                    }
                                } catch (Exception e) {
                                }
                            } catch (Exception e) {
                                log.error("没有配置该节点审核人/审核组");
                            }
                        }
                    }
                    if (null != assignUsers && !assignUsers.isEmpty()) {
                        for (String user : assignUsers) {
                            taskService.addCandidateUser(nextTaskId, user);
                        }
                    }
                    if (null != assignGroups && !assignGroups.isEmpty()) {
                        for (String group : assignGroups) {
                            taskService.addCandidateGroup(nextTaskId, group);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("assign users/groups error!", e);
            throw new MyException(CodeEnum.commonException);
        }

    }
}
